package com.platform.utils;

import com.platform.exception.BaseException;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Base64Utils {

   final static Base64.Encoder encoder = Base64.getEncoder();
   final static Base64.Decoder decoder = Base64.getDecoder();

   final static Pattern htmlBase64ImagePattern = Pattern.compile("<img\\s+[^>]*src=[\"']data:image\\/([^;]+);base64,([^\"']+)[\"'][^>]*>", Pattern.CASE_INSENSITIVE);

   final static Pattern base64ImagePattern = Pattern.compile("^data:image/(\\w+);base64,(.*)$", Pattern.CASE_INSENSITIVE);

   /**
    * 获取Base64图片类型
    *
    * @param base64Code base64编码
    * @return 文件类型
    */
   public static String getImageType(String base64Code) {
      // 正则表达式匹配 Base64 图片
      Matcher matcher = base64ImagePattern.matcher(base64Code);

      if (matcher.find()) {
         return matcher.group(1);
      }
      return null;
   }

   /**
    * 拆分Base64图片类型和编码
    *
    * @param base64Code base64编码
    * @return imageType文件类型，base64Data图片编码
    */
   public static Map<String, String> splitImageTypeAndCode(String base64Code) {
      // 正则表达式匹配 Base64 图片
      Matcher matcher = base64ImagePattern.matcher(base64Code);
      Map<String, String> res = new HashMap<>();
      if (matcher.find()) {
         res.put("imageType", matcher.group(1));
         res.put("base64Data", matcher.group(2));
         return res;
      }
      return null;
   }

   public static String encode(String text) {
      byte[] textByte = new byte[0];
      try {
         textByte = text.getBytes("UTF-8");
      } catch (UnsupportedEncodingException e) {
         e.printStackTrace();
      }
      String encodedText = encoder.encodeToString(textByte);
      return encodedText;
   }

  
   public static String decode(String encodedText) {
      String text = null;
      try {
         text = new String(decoder.decode(encodedText), "UTF-8");
      } catch (UnsupportedEncodingException e) {
         e.printStackTrace();
      }
      return text;
   }

   public static MultipartFile convertBase64ToMultipart(String base64Image, String fileName) throws IOException {
      if (base64Image == null) {
         throw new BaseException("base64Image为空");
      }
      if (fileName == null) {
         throw new BaseException("fileName为空");
      }

      // 去除base64字符串中的前缀（如果有的话）
      String base64Data = base64Image.replaceFirst("data:image/png;base64,", "").replaceFirst("data:image/jpeg;base64,", "");

      // 解码base64字符串为字节数组
      byte[] imageBytes = Base64.getDecoder().decode(base64Data);

      // 创建ByteArrayResource
      ByteArrayResource resource = new ByteArrayResource(imageBytes);

      // 使用MockMultipartFile来创建MultipartFile对象
      MultipartFile multipartFile = new MockMultipartFile(
              "file", // 参数名
              fileName, // 文件名
              "image/png", // 文件类型
              resource.getInputStream() // 输入流
      );

      return multipartFile;
   }

   /**
    * 移除 Base64 字符串中的前缀（如 data:image/png;base64,）
    *
    * @param base64String 带有前缀的 Base64 字符串
    * @return 移除前缀后的 Base64 字符串
    */
   public static String removeBase64Prefix(String base64String) {
      // 定义常见的前缀分隔符
      String prefixSeparator = ",";
      int separatorIndex = base64String.indexOf(prefixSeparator);

      // 如果找到了分隔符，则返回分隔符之后的部分
      if (separatorIndex != -1) {
         return base64String.substring(separatorIndex + 1);
      }

      // 如果没有找到分隔符，返回原始字符串
      return base64String;
   }

   /**
    * 将指定 URL 的图片转换为 Base64 编码的字符串
    *
    * @param imageUrl 图片的 URL
    * @return Base64 编码的字符串
    * @throws IOException 如果在读取 URL 时发生错误
    */
   public static String convertImageUrlToBase64(String imageUrl) throws IOException {
      // 打开 URL 连接并获取输入流
//      URL url = new URL(imageUrl);
//      try (InputStream inputStream = url.openStream();
//           ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
//
//         // 缓冲区
//         byte[] buffer = new byte[1024];
//         int bytesRead;
//
//         // 读取数据并写入字节数组输出流
//         while ((bytesRead = inputStream.read(buffer)) != -1) {
//            byteArrayOutputStream.write(buffer, 0, bytesRead);
//         }
//
//         // 将字节数组转换为 Base64 编码的字符串
//         byte[] imageBytes = byteArrayOutputStream.toByteArray();
//         return Base64.getEncoder().encodeToString(imageBytes);
//      }
      // 获取图像的格式
      String fileType = getImageFileType(imageUrl);
      if (fileType == null) {
         throw new IOException("Unable to determine image file type.");
      }

      // 打开 URL 连接并获取输入流
      URL url = new URL(imageUrl);
      try (InputStream inputStream = url.openStream();
           ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

         // 缓冲区
         byte[] buffer = new byte[1024];
         int bytesRead;

         // 读取数据并写入字节数组输出流
         while ((bytesRead = inputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, bytesRead);
         }

         // 将字节数组转换为 Base64 编码的字符串
         byte[] imageBytes = byteArrayOutputStream.toByteArray();
         String base64Image = Base64.getEncoder().encodeToString(imageBytes);

         // 返回带有前缀的 Base64 编码字符串
         return "data:image/" + fileType + ";base64," + base64Image;
      }
   }

   /**
    * 根据imageUrl获取图片后缀
    *
    * @param imageUrl url
    * @return 格式
    * @throws IOException 异常
    */
   private static String getImageFileType(String imageUrl) throws IOException {
      // 打开 URL 连接并获取输入流
      URL url = new URL(imageUrl);
      try (InputStream inputStream = url.openStream()) {
         byte[] header = new byte[8];
         int bytesRead = inputStream.read(header, 0, header.length);

         if (bytesRead < 2) {
            return null; // 文件头太短，无法识别
         }

         // 检查 JPEG 魔数
         if ((header[0] & 0xFF) == 0xFF && (header[1] & 0xFF) == 0xD8) {
            return "jpeg";
         }

         // 检查 PNG 魔数
         if (bytesRead >= 8 &&
                 (header[0] & 0xFF) == 0x89 &&
                 (header[1] & 0xFF) == 0x50 &&
                 (header[2] & 0xFF) == 0x4E &&
                 (header[3] & 0xFF) == 0x47 &&
                 (header[4] & 0xFF) == 0x0D &&
                 (header[5] & 0xFF) == 0x0A &&
                 (header[6] & 0xFF) == 0x1A &&
                 (header[7] & 0xFF) == 0x0A) {
            return "png";
         }

         // 检查 GIF 魔数
         if (bytesRead >= 6 &&
                 (header[0] & 0xFF) == 0x47 &&
                 (header[1] & 0xFF) == 0x49 &&
                 (header[2] & 0xFF) == 0x46) {
            return "gif";
         }

         // 检查 BMP 魔数
         if ((header[0] & 0xFF) == 0x42 && (header[1] & 0xFF) == 0x4D) {
            return "bmp";
         }

         // 检查 TIFF 魔数
         if ((header[0] & 0xFF) == 0x49 && (header[1] & 0xFF) == 0x49 &&
                 (header[2] & 0xFF) == 0x2A && (header[3] & 0xFF) == 0x00) {
            return "tiff";
         }

         if ((header[0] & 0xFF) == 0x4D && (header[1] & 0xFF) == 0x4D &&
                 (header[2] & 0xFF) == 0x00 && (header[3] & 0xFF) == 0x2A) {
            return "tiff";
         }

         // 无法识别的文件类型
         return null;
      }
   }

   /**
    * 为base64编码添加上水印
    *
    * @param base64Image base64编码
    * @return 添加水印的base64编码
    */
   public static String addWatermark(String base64Image) {
      try {
         String base64Prefix = null;

         // 去除Base64前缀
         if (base64Image.contains(",")) {
            base64Prefix = base64Image.split(",")[0];
            base64Image = base64Image.split(",")[1];
         }

         // 解码Base64图像
         byte[] decodedBytes = Base64.getDecoder().decode(base64Image);
         BufferedImage image = ImageIO.read(new ByteArrayInputStream(decodedBytes));

         // 创建图形环境
         Graphics2D g2d = image.createGraphics();
         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
         g2d.setFont(new Font("Arial", Font.BOLD, 30));
         g2d.setColor(new Color(255, 255, 255, 128)); // 白色半透明

         // 获取图像尺寸
         int width = image.getWidth();
         int height = image.getHeight();

         // 设置水印位置（右下角）
         int x = width - 200;
         int y = height - 50;

         // 获取当前时间的毫秒数并转换为字符串
         String watermarkText = String.valueOf(System.currentTimeMillis());

         // 添加水印
         g2d.drawString(watermarkText, x, y);
         g2d.dispose();

         // 将图像编码回Base64
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ImageIO.write(image, "png", baos);
         byte[] encodedBytes = Base64.getEncoder().encode(baos.toByteArray());
         return new StringBuilder().append("data:image/png;base64,").append(new String(encodedBytes)).toString();

      } catch (Exception e) {
         e.printStackTrace();
         return null;
      }
   }
}

